#ifndef __SG_RING_BUFFER__
#define __SG_RING_BUFFER__

#include <vector>
#include <string>

// https://www.cnblogs.com/l00l/p/4115001.html
// only one thread read and one thread write.
class RingBuffer
{
    public:
        RingBuffer():
            head(0),
            tail(0)
        {
            buffer = new std::string[bufferSize];
        };
        virtual ~RingBuffer()
        {
            delete[] buffer;
        };
        bool put(const std::string& v) {
            if (full()) {
                return false;
            }
            buffer[tail] = v;
            tail = (tail + 1) % bufferSize;
            return true;

        };
        std::string get() {
            if (empty()) {
                return std::string();
            }
            std::string result = buffer[head];
            head = (head + 1) % bufferSize;
            return result;
        };
        std::vector<std::string> getAll() {
            std::vector<std::string> result;
            if (empty()) {
                return result;
            }
            int copyTail = tail;
            int cnt = head < copyTail ? copyTail - head : bufferSize - head + copyTail;
            result.reserve(cnt);
            if (head < copyTail) {
                for (int i = head; i < copyTail; i++) {
                    result[i - head] = buffer[i];
                }
            } else {
                for (int i = head; i < bufferSize; i++) {
                    result[i - head] = buffer[i];
                }
                for (int i = 0; i < copyTail; i++) {
                    result[bufferSize - head + i] = buffer[i];
                }
            }
            head = copyTail;
            return result;
        };

    private:
        const static int bufferSize = 1024;
        int head;
        int tail;
        std::string* buffer;

    private:
        bool empty() {
            return head == tail;
        };
        bool full() {
            return (tail + 1) % bufferSize == head;
        };
};


#endif

